/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "bridge/cj_frontend/interfaces/cj_ffi/cj_navigation_ffi.h"

#include "bridge/cj_frontend/interfaces/cj_ffi/cj_collection_ffi.h"
#ifdef NAVIGATION_SUPPORTED
#include "core/components_ng/pattern/navigation/navigation_declaration.h"
#include "core/components_ng/pattern/navigation/navigation_model.h"
#endif
#include "core/components_ng/base/view_stack_processor.h"
#include "cj_lambda.h"

using namespace Keels::Ace;
using namespace Keels::Ace::Framework;

#ifdef NAVIGATION_SUPPORTED
namespace Keels::Ace {

void ParseBarItems(const std::vector<NavigationItem>& items, std::vector<NG::BarItem>& barItems)
{
    for (size_t i = 0; i < items.size(); i++) {
        NG::BarItem toolBarItem;
        toolBarItem.text = items[i].value;
        toolBarItem.icon = items[i].icon;
        auto builderFunc = items[i].builder;
        auto onItemClick = [func = std::move(builderFunc)]() { func(); };
        LOGD("ParseBarItems text: %{public}s, icon: %{public}s", toolBarItem.text->c_str(), toolBarItem.icon->c_str());
        toolBarItem.action = onItemClick;
        barItems.push_back(toolBarItem);
    }
}

} // namespace Keels::Ace
#endif

extern "C" {
void FfiOHOSAceFrameworkNavigationCreate()
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->Create();
#endif
}

void FfiOHOSAceFrameworkNavigationSetTitle(const char* title)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetTitle(title);
#endif
}

void FfiOHOSAceFrameworkNavigationSetTitleWithBuilder(void (*builder)())
{
#ifdef NAVIGATION_SUPPORTED
    auto builderFunc = CJLambda::Create(builder);
    RefPtr<NG::UINode> customNode;
    {
        NG::ScopedViewStackProcessor builderViewStackProcessor;
        builderFunc();
        customNode = NG::ViewStackProcessor::GetInstance()->Finish();
    }
    NavigationModel::GetInstance()->SetCustomTitle(customNode);
#endif
}

void FfiOHOSAceFrameworkNavigationSetSubTitle(const char* subTitle)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetSubtitle(subTitle);
#endif
}

void FfiOHOSAceFrameworkNavigationSetMenus(VectorNavigationItemHandle menus)
{
#ifdef NAVIGATION_SUPPORTED
    const auto& menuVector = *reinterpret_cast<std::vector<NavigationItem>*>(menus);
    std::vector<NG::BarItem> menuItems;
    ParseBarItems(menuVector, menuItems);
    NavigationModel::GetInstance()->SetMenuItems(std::move(menuItems));
#endif
}

void FfiOHOSAceFrameworkNavigationSetMenusWithBuilder(void (*builder)())
{
#ifdef NAVIGATION_SUPPORTED
    auto builderFunc = CJLambda::Create(builder);
    RefPtr<NG::UINode> customNode;
    {
        NG::ScopedViewStackProcessor builderViewStackProcessor;
        builderFunc();
        customNode = NG::ViewStackProcessor::GetInstance()->Finish();
    }
    NavigationModel::GetInstance()->SetCustomMenu(customNode);
#endif
}

void FfiOHOSAceFrameworkNavigationSetTitleMode(int32_t titleMode)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetTitleMode(static_cast<NG::NavigationTitleMode>(titleMode));
#endif
}

void FfiOHOSAceFrameworkNavigationSetToolBar(VectorNavigationItemHandle toolBars)
{
#ifdef NAVIGATION_SUPPORTED
    const auto& toolBarVector = *reinterpret_cast<std::vector<NavigationItem>*>(toolBars);
    std::vector<NG::BarItem> toolBarItems;
    ParseBarItems(toolBarVector, toolBarItems);
    NavigationModel::GetInstance()->SetToolBarItems(std::move(toolBarItems));
#endif
}

void FfiOHOSAceFrameworkNavigationSetToolBarWithBuilder(void (*builder)())
{
#ifdef NAVIGATION_SUPPORTED
    auto builderFunc = CJLambda::Create(builder);
    RefPtr<NG::UINode> customNode;
    {
        NG::ScopedViewStackProcessor builderViewStackProcessor;
        builderFunc();
        customNode = NG::ViewStackProcessor::GetInstance()->Finish();
    }
    NavigationModel::GetInstance()->SetCustomToolBar(customNode);
#endif
}

void FfiOHOSAceFrameworkNavigationSetHideToolBar(bool isHide)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetHideToolBar(isHide);
#endif
}

void FfiOHOSAceFrameworkNavigationSetHideTitleBar(bool isHide)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetHideTitleBar(isHide);
#endif
}

void FfiOHOSAceFrameworkNavigationSetHideBackButton(bool isHide)
{
#ifdef NAVIGATION_SUPPORTED
    NavigationModel::GetInstance()->SetHideBackButton(isHide);
#endif
}

void FfiOHOSAceFrameworkNavigationSetOnTitleModeChanged(void (*callback)(int32_t))
{
#ifdef NAVIGATION_SUPPORTED
    auto onChange = CJLambda::Create(callback);
    auto onTitleModeChange = [func = std::move(onChange)](
                                 NG::NavigationTitleMode mode) { func(static_cast<int32_t>(mode)); };
    NavigationModel::GetInstance()->SetOnTitleModeChange(std::move(onTitleModeChange), [](auto) {});
#endif
}
}
